package core.matrix;

import core.iterfaces.Matrix;
import core.iterfaces.Vec;
import core.vec.DenseVec;
import exception.NotSupportException;

/**
 * 稠密矩阵，使用二维数组存储
 */
public class DenseMatrix implements Matrix {
    /**
     * 二维数组
     */
    private Double[][] data;
    /**
     * 行长度
     */
    private Integer rowLen;
    /**
     * 列长度
     */
    private Integer colLen;

    /**
     * 构造函数
     * @param rowLen 行长度
     * @param colLen 列长度
     */
    public DenseMatrix(Integer rowLen,Integer colLen){
        this.rowLen = rowLen;
        this.colLen = colLen;
        data = new Double[this.rowLen][this.colLen];
        init();
    }

    /**
     * 构造函数，构造 0x0的矩阵
     */
    public DenseMatrix(){
        this.rowLen =0;
        this.colLen =0;
        data = new Double[this.rowLen][this.colLen];
        init();
    }

    /**
     * 初始化数组元素
     */
    private void init(){
        for(int i=0;i<rowLen;i++){
            for(int j=0;j<colLen;j++){
                data[i][j]=0.0;
            }
        }
    }


    public Matrix copy(){
        DenseMatrix result = new DenseMatrix(this.rowLen,this.colLen);
        for (int i = 0; i < rowLen; i++) {
            for (int j = 0; j < colLen; j++) {
                result.set(i,j,get(i,j));
            }
        }
        return result;
    }


    @Override
    public Matrix zero() {
        return new DenseMatrix(this.rowLen,this.colLen);
    }

    @Override
    public Matrix zero(int rowLen, int colLen) {
        return new DenseMatrix(rowLen,colLen);
    }

    @Override
    public double get(int i, int j) {
        if(i<0||i>rowLen-1){
            throw new IndexOutOfBoundsException("传入的参数i:"+i+" 不符合矩阵行数范围");
        }
        if(j<0||j>colLen-1){
            throw new IndexOutOfBoundsException("传入的参数j:"+j+" 不符合矩阵列数范围");
        }
        return data[i][j];
    }

    @Override
    public void set(int i, int j, double value) {
        if(i<0||i>rowLen-1){
            throw new IndexOutOfBoundsException("传入的参数i:"+i+" 不符合矩阵行数范围");
        }
        if(j<0||j>colLen-1){
            throw new IndexOutOfBoundsException("传入的参数j:"+j+" 不符合矩阵列数范围");
        }
        data[i][j] = value;
    }

    @Override
    public Vec getRow(int i) throws NotSupportException {
        if(i<0||i>rowLen-1){
            throw new IndexOutOfBoundsException("传入的参数i:"+i+" 不符合矩阵行数范围");
        }
        return new DenseVec(data[i],true);
    }

    @Override
    public Vec getCol(int j) {
        if(j<0||j>colLen-1){
            throw new IndexOutOfBoundsException("传入的参数j:"+j+" 不符合矩阵列数范围");
        }
        Double[] col = new Double[colLen];
        for (int i = 0; i < colLen; i++) {
            col[i]=data[i][j];
        }
        return new DenseVec(col,false);
    }

    @Override
    public Vec getSubRow(int i, int begin, int end) throws NotSupportException {
        if(i<0||i>rowLen-1){
            throw new IndexOutOfBoundsException("传入的参数i:"+i+" 不符合矩阵行数范围");
        }
        if(begin>end){
            throw new IndexOutOfBoundsException("传入的参数begin:"+begin+" 不能大于end");
        }
        if(begin<0||begin>colLen-1){
            throw new IndexOutOfBoundsException("传入的参数begin范围超限制");
        }
        if(end<0||end>colLen-1){
            throw new IndexOutOfBoundsException("传入的参数end范围超限制");
        }
        Double[] result = new  Double[end-begin];
        System.arraycopy(data[i],begin,result,0,end-begin);
        return new DenseVec(result,false);
    }

    @Override
    public Vec getSubCol(int j, int begin, int end) throws NotSupportException {
        if(j<0||j>colLen-1){
            throw new IndexOutOfBoundsException("传入的参数j:"+j+" 不符合矩阵列数范围");
        }
        if(begin>end){
            throw new IndexOutOfBoundsException("传入的参数begin:"+begin+" 不能大于end");
        }
        if(begin<0||begin>rowLen-1){
            throw new IndexOutOfBoundsException("传入的参数begin范围超限制");
        }
        if(end<0||end>rowLen-1){
            throw new IndexOutOfBoundsException("传入的参数end范围超限制");
        }
        Double[] result = new  Double[end-begin];
        for (int i = 0; i < result.length; i++) {
            result[i] = data[begin+i][j];
        }
        return new DenseVec(result,false);
    }


    @Override
    public int getRowLen() {
        return rowLen;
    }

    @Override
    public int getColLen() {
        return colLen;
    }

    @Override
    public boolean isDense() {
        return true;
    }

    @Override
    public boolean isPositiveDefinite() {
        return false;
    }

    @Override
    public double norm2() {
        return 0;
    }

    @Override
    public Matrix toSparse() throws NotSupportException {
        SparseMatrix result = new SparseMatrix();
        for(int i=0;i<rowLen;i++){
            for (int j = 0; j < colLen; j++) {
                result.set(i,j,get(i,j));
            }
        }
        return result;
    }

    @Override
    public Matrix toDense() throws NotSupportException {
        return this.copy();
    }
}
